#include <pcap.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <netinet/if_ether.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>

// Function to get current time as string
void get_current_time(char *time_buf) {
    time_t now = time(NULL);
    struct tm *t = localtime(&now);
    strftime(time_buf, 20, "%Y-%m-%d %H:%M:%S", t);
}

// Function to format MAC address
void format_mac_address(const u_char *mac, char *mac_buf) {
    sprintf(mac_buf, "%02X-%02X-%02X-%02X-%02X-%02X", 
            mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
}

// Function to extract FTP credentials from packet payload
int extract_ftp_credentials(const u_char *payload, int payload_len, 
                           char *username, char *password, char *status) {
    char *data = (char *)payload;
    
    // Look for USER command (username)
    if (strstr(data, "USER ") != NULL) {
        char *user_start = strstr(data, "USER ") + 5;
        char *user_end = strchr(user_start, '\r');
        if (user_end != NULL) {
            int user_len = user_end - user_start;
            strncpy(username, user_start, user_len);
            username[user_len] = '\0';
            return 1; // Found username
        }
    }
    
    // Look for PASS command (password)
    if (strstr(data, "PASS ") != NULL) {
        char *pass_start = strstr(data, "PASS ") + 5;
        char *pass_end = strchr(pass_start, '\r');
        if (pass_end != NULL) {
            int pass_len = pass_end - pass_start;
            strncpy(password, pass_start, pass_len);
            password[pass_len] = '\0';
            return 2; // Found password
        }
    }
    
    // Look for login success (230)
    if (strstr(data, "230 ") != NULL) {
        strcpy(status, "SUCCESS");
        return 3; // Found success
    }
    
    // Look for login failure (530)
    if (strstr(data, "530 ") != NULL) {
        strcpy(status, "FAILED");
        return 4; // Found failure
    }
    
    return 0; // No FTP credentials found
}

// Packet handler function
void packet_handler(u_char *args, const struct pcap_pkthdr *header, const u_char *packet) {
    struct ethhdr *eth_header = (struct ethhdr *)packet;
    
    // Check if it's an IP packet
    if (ntohs(eth_header->h_proto) == ETH_P_IP) {
        struct iphdr *ip_header = (struct iphdr *)(packet + sizeof(struct ethhdr));
        
        // Check if it's TCP and port 21 (FTP)
        if (ip_header->protocol == IPPROTO_TCP) {
            struct tcphdr *tcp_header = (struct tcphdr *)(packet + sizeof(struct ethhdr) + (ip_header->ihl * 4));
            
            if (ntohs(tcp_header->dest) == 21 || ntohs(tcp_header->source) == 21) {
                // Calculate TCP payload (FTP data)
                int ip_header_len = ip_header->ihl * 4;
                int tcp_header_len = tcp_header->doff * 4;
                const u_char *payload = packet + sizeof(struct ethhdr) + ip_header_len + tcp_header_len;
                int payload_len = ntohs(ip_header->tot_len) - ip_header_len - tcp_header_len;
                
                if (payload_len > 0) {
                    char username[64] = "";
                    char password[64] = "";
                    char status[16] = "UNKNOWN";
                    
                    // Extract FTP credentials
                    int result = extract_ftp_credentials(payload, payload_len, username, password, status);
                    
                    // If we found any FTP login information, log it
                    if (result > 0) {
                        // Get current time
                        char time_str[20];
                        get_current_time(time_str);
                        
                        // Format MAC addresses
                        char src_mac[18], dst_mac[18];
                        format_mac_address(eth_header->h_source, src_mac);
                        format_mac_address(eth_header->h_dest, dst_mac);
                        
                        // Format IP addresses
                        char src_ip[16], dst_ip[16];
                        sprintf(src_ip, "%d.%d.%d.%d", 
                                (ip_header->saddr) & 0xFF,
                                (ip_header->saddr >> 8) & 0xFF,
                                (ip_header->saddr >> 16) & 0xFF,
                                (ip_header->saddr >> 24) & 0xFF);
                        sprintf(dst_ip, "%d.%d.%d.%d", 
                                (ip_header->daddr) & 0xFF,
                                (ip_header->daddr >> 8) & 0xFF,
                                (ip_header->daddr >> 16) & 0xFF,
                                (ip_header->daddr >> 24) & 0xFF);
                        
                        // Output to CSV file
                        FILE *log_file = fopen("ftp_login_log.csv", "a");
                        if (log_file != NULL) {
                            fprintf(log_file, "%s,%s,%s,%s,%s,%s,%s,%s\n", 
                                    time_str, src_mac, src_ip, dst_mac, dst_ip, 
                                    username, password, status);
                            fclose(log_file);
                        }
                        
                        // Also print to console
                        printf("%s,%s,%s,%s,%s,%s,%s,%s\n", 
                               time_str, src_mac, src_ip, dst_mac, dst_ip, 
                               username, password, status);
                    }
                }
            }
        }
    }
}

int main() {
    char errbuf[PCAP_ERRBUF_SIZE];
    pcap_t *handle;
    
    printf("Starting FTP login sniffer...\n");
    printf("Output format: Time,Source MAC,Source IP,Destination MAC,Destination IP,Username,Password,Status\n");
    
    // Open network interface for capture
    handle = pcap_open_live("lo", BUFSIZ, 1, 1000, errbuf);
    if (handle == NULL) {
        fprintf(stderr, "Error opening device: %s\n", errbuf);
        return 1;
    }
    
    // Set filter to capture only FTP traffic (port 21)
    struct bpf_program fp;
    char filter_exp[] = "tcp port 21";
    if (pcap_compile(handle, &fp, filter_exp, 0, PCAP_NETMASK_UNKNOWN) == -1) {
        fprintf(stderr, "Couldn't parse filter %s: %s\n", filter_exp, pcap_geterr(handle));
        return 1;
    }
    if (pcap_setfilter(handle, &fp) == -1) {
        fprintf(stderr, "Couldn't install filter %s: %s\n", filter_exp, pcap_geterr(handle));
        return 1;
    }
    
    // Create CSV file with header
    FILE *log_file = fopen("ftp_login_log.csv", "w");
    if (log_file != NULL) {
        fprintf(log_file, "Time,Source MAC,Source IP,Destination MAC,Destination IP,Username,Password,Status\n");
        fclose(log_file);
    }
    
    printf("FTP login capture started. Press Ctrl+C to stop.\n");
    
    // Start packet capture loop
    pcap_loop(handle, 0, packet_handler, NULL);
    
    pcap_close(handle);
    return 0;
}
